package com.android.inputmethod.pinyin;

import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.GestureDetector;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.constraintlayout.widget.ConstraintLayout;
import androidx.core.view.GestureDetectorCompat;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import com.google.android.flexbox.AlignItems;
import com.google.android.flexbox.FlexDirection;
import com.google.android.flexbox.FlexWrap;
import com.google.android.flexbox.FlexboxLayoutManager;
import com.google.android.flexbox.JustifyContent;

import java.util.ArrayList;

public class LancooCandidateView extends ConstraintLayout implements View.OnClickListener {
    /**
     * Decoding result to show.
     */
    private LancooPinyinIME.DecodingInfo mDecInfo;

    public LancooCandidateView(@NonNull Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    private RecyclerView mSmallView;
    private RecyclerView mAllView;

    private DataAdapter mSmallAdapter;
    private DataAdapter mAllAdapter;
    private LancooCandidateViewListener mCandidateViewListener;

    @Override
    protected void onFinishInflate() {
        super.onFinishInflate();
        mSmallView = findViewById(R.id.small_candidates);
        mAllView = findViewById(R.id.all_candidates);

        Context context = getContext();
        mSmallView.setLayoutManager(new LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false));
        mSmallAdapter = new DataAdapter();
        mSmallView.setAdapter(mSmallAdapter);

        FlexboxLayoutManager manager = new FlexboxLayoutManager(context);
        manager.setFlexWrap(FlexWrap.WRAP);
        manager.setFlexDirection(FlexDirection.ROW);
        manager.setJustifyContent(JustifyContent.SPACE_BETWEEN);
        manager.setAlignItems(AlignItems.BASELINE);
        mAllView.setLayoutManager(manager);
        mAllAdapter = new DataAdapter(true);
        mAllView.setAdapter(mAllAdapter);
        showAllOrNot(false);

        findViewById(R.id.iv_candidates_arrow).setOnClickListener(this);
        findViewById(R.id.btn_back).setOnClickListener(this);
        findViewById(R.id.btn_delete).setOnClickListener(this);
        findViewById(R.id.btn_reset).setOnClickListener(this);

        mSmallView.addOnItemTouchListener(new OnItemClickListener(mSmallView) {
            @Override
            public boolean onItemClick(RecyclerView.ViewHolder viewHolder) {
                int position = viewHolder.getLayoutPosition();
                String resultStr = mSmallAdapter.dataList.get(position);
                mCandidateViewListener.onClickChoice(resultStr);
                return true;
            }
        });
        mAllView.addOnItemTouchListener(new OnItemClickListener(mAllView) {
            @Override
            public boolean onItemClick(RecyclerView.ViewHolder viewHolder) {
                int position = viewHolder.getLayoutPosition();
                String resultStr = mAllAdapter.dataList.get(position);
                mCandidateViewListener.onClickChoice(resultStr);
                return true;
            }
        });
    }

    public void initialize(LancooCandidateViewListener listener) {
        mCandidateViewListener = listener;
    }

    public void showCandidates(LancooPinyinIME.DecodingInfo decInfo) {
        if (mSmallView == null) return;
        mDecInfo = decInfo;

        mSmallAdapter.dataList.clear();
        readCandidates();// mDecInfo默认查找第一页
        if (mSmallAdapter.dataList.isEmpty()) {// 没有发现中文，直接展示英文及其大写
            String str = mDecInfo.getComposingStrForDisplay();
            mSmallAdapter.dataList.add(str);
            mSmallAdapter.dataList.add(str.toUpperCase());
        }
        mSmallAdapter.notifyDataSetChanged();

        setVisibility(VISIBLE);
    }

    public void hideCandidates() {
        setVisibility(GONE);
        showAllOrNot(false);
    }

    private void readCandidates() {
        Log.e("My", "============================");
        Log.e("My", mDecInfo.mPageStart.toString());
        Log.e("My", mDecInfo.mCandidatesList.toString());
        int pageSize = mDecInfo.mPageStart.size();
        for (int pageNo = 0; pageNo < pageSize; pageNo++) {
            int pStart = mDecInfo.mPageStart.get(pageNo);
            int pSize;
            if (pageNo + 1 < pageSize) {
                pSize = mDecInfo.mPageStart.get(pageNo + 1) - pStart;
            } else {
                pSize = mDecInfo.mCandidatesList.size() - pStart;
            }
            for (int i = 0; i < pSize; i++) {
                String cand = mDecInfo.mCandidatesList.get(pStart + i);
                mSmallAdapter.dataList.add(cand);
            }
        }
    }

    private void readAllCandidates() {
        Log.e("My", "readAllCandidates============================");
        int currentPage = 0;
        while (mDecInfo.preparePage(currentPage)) {
            calculatePage(currentPage);
            currentPage++;
        }
        Log.e("My", mDecInfo.mPageStart.size() + " <---> " + mDecInfo.mCandidatesList.size());
        Log.e("My", mDecInfo.mPageStart.toString());
        Log.e("My", mDecInfo.mCandidatesList.toString());
        mAllAdapter.dataList.clear();
        int size = mDecInfo.mCandidatesList.size();
        for (int i = 0; i < size; i++) {
            String cand = mDecInfo.mCandidatesList.get(i);
            mAllAdapter.dataList.add(cand);
        }
        mAllAdapter.notifyDataSetChanged();
    }

    private void showAllOrNot(boolean isShow) {
        int visible = isShow ? VISIBLE : GONE;
        mAllView.setVisibility(visible);
        findViewById(R.id.all_candidates_btn).setVisibility(visible);
    }

    private void calculatePage(int pageNo) {
        int candSize = mDecInfo.mCandidatesList.size();

        // If the size of page exists, only calculate the extra margin.
        boolean onlyExtraMargin = false;
        int fromPage = mDecInfo.mPageStart.size() - 1;
        if (mDecInfo.mPageStart.size() > pageNo + 1) {
            onlyExtraMargin = true;
            fromPage = pageNo;
        }

        // If the previous pages have no information, calculate them first.
        for (int p = fromPage; p <= pageNo; p++) {
            int pStart = mDecInfo.mPageStart.get(p);
            int pSize = 0;

            while (pStart + pSize < candSize) {
                if (0 == pSize) {
                    pSize++;
                } else {
                    break;
                }
            }
            if (!onlyExtraMargin) {
                mDecInfo.mPageStart.add(pStart + pSize);
            }
        }
    }

    /*@Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        Environment env = Environment.getInstance();
        int measuredWidth = env.getScreenWidth();
        int measuredHeight = getPaddingTop();
        measuredHeight += env.getHeightForCandidates();
        widthMeasureSpec = MeasureSpec.makeMeasureSpec(measuredWidth, MeasureSpec.EXACTLY);
        heightMeasureSpec = MeasureSpec.makeMeasureSpec(measuredHeight, MeasureSpec.EXACTLY);
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }*/

    @Override
    public void onClick(View v) {
        int id = v.getId();
        if (id == R.id.iv_candidates_arrow) {
            if (mAllView.getVisibility() == View.VISIBLE) {
                showAllOrNot(false);
                return;
            }

            readAllCandidates();
            if (mAllAdapter.dataList.isEmpty()) return;

            ViewGroup.LayoutParams lp = mAllView.getLayoutParams();
            lp.height = Environment.getInstance().getSkbHeight() + mSmallView.getHeight();
            mAllView.setLayoutParams(lp);

            showAllOrNot(true);
        } else if (id == R.id.btn_back) {
            showAllOrNot(false);
        } else if (id == R.id.btn_delete) {
            mCandidateViewListener.onDelete();
            readAllCandidates();
            if (mSmallAdapter.dataList.isEmpty()) {
                showAllOrNot(false);
            }
        } else if (id == R.id.btn_reset) {
            mCandidateViewListener.onReset();
        }
    }

    private static class DataAdapter extends RecyclerView.Adapter<DataViewHolder> {
        private boolean isForAll;
        private final ArrayList<String> dataList = new ArrayList<>();

        public DataAdapter() {
        }

        public DataAdapter(boolean isForAll) {
            this.isForAll = isForAll;
        }

        @Override
        public int getItemCount() {
            return dataList.size();
        }

        @NonNull
        @Override
        public DataViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
            TextView tv = new TextView(parent.getContext());
            tv.setTextSize(18);
            tv.setGravity(Gravity.CENTER_VERTICAL);

            int padding = 15;
            if (isForAll) {
                tv.setPadding(padding, padding, padding, padding);
                tv.setLayoutParams(new FlexboxLayoutManager.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
            } else {
                tv.setPadding(padding, 0, padding, 0);
                tv.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.MATCH_PARENT));
            }

            return new DataViewHolder(tv);
        }

        @Override
        public void onBindViewHolder(@NonNull DataViewHolder holder, int position) {
            holder.tv.setText(dataList.get(position));
        }
    }

    private static class DataViewHolder extends RecyclerView.ViewHolder {
        TextView tv;

        public DataViewHolder(@NonNull View itemView) {
            super(itemView);
            tv = (TextView) itemView;
        }
    }

    public interface CandidateViewListener {
        public void onClickChoice(int choiceId);
    }

    private static class OnItemClickListener implements RecyclerView.OnItemTouchListener {
        private GestureDetectorCompat mGestureDetectorCompat;
        protected RecyclerView mRecyclerView;

        public OnItemClickListener(RecyclerView recyclerView) {
            mRecyclerView = recyclerView;
            mGestureDetectorCompat = new GestureDetectorCompat(mRecyclerView.getContext(), new ItemTouchGestureListener());
        }

        @Override
        public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
            return mGestureDetectorCompat.onTouchEvent(e);
        }

        @Override
        public void onTouchEvent(RecyclerView rv, MotionEvent e) {
        }

        @Override
        public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {
        }

        public boolean onItemClick(RecyclerView.ViewHolder viewHolder) {
            return false;
        }

        private class ItemTouchGestureListener extends GestureDetector.SimpleOnGestureListener {
            @Override
            public boolean onSingleTapUp(MotionEvent e) {
                View childViewUnder = mRecyclerView.findChildViewUnder(e.getX(), e.getY());
                if (childViewUnder != null) {
                    RecyclerView.ViewHolder childViewHolder = mRecyclerView.getChildViewHolder(childViewUnder);
                    if (onItemClick(childViewHolder)) {
                        return true;
                    }
                }
                return false;
            }
        }
    }
}